
import java.util.Scanner;
import java.io.*;

import application.*;
import dataStructures.*;

/**
 * @author Carlos Duarte - 43796
 * @author Rafael Florencio - 43829
 */
public class Main {

	private enum COMMAND{
		AD, PC, AT, RT, LT, LR, LE, FP, LF
	}

	private static final String ACTDICIONARIO = "Atualizacao do dicionario com sucesso.";
	private static final String NAOACTDICIONARIO = "Lista de palavras nao contem palavras novas.";
	private static final String EXISTEDICIONARIO = "Palavra correta.";
	private static final String NAOEXISTEDICIONARIO = "Erro ortografico.";
	private static final String ADDTEXT = "Texto adicionado com sucesso.";
	private static final String NAOADDTEXT = "Identificador de texto existente.";
	private static final String REMOVERTEXTO = "Remocao de texto com sucesso.";
	private static final String NAOREMOVERTEXTO = "Texto inexistente.";
	private static final String NAOERROR = "Inexistencia de erros ortograficos no texto.";
	private static final String LINHASTROCADAS = "Intervalo de numero de linhas mal definido.";
	private static final String LINHASMAXIMASERRADAS = "Troco inexistente.";
	private static final String NUMOCORRENCIAS = "%s ocorre %d vezes no texto referido.";
	private static final String PALAVRASFREQUENCIA ="Inexistencia de palavras com a frequencia pedida.";
	/**
	 * @param args
	 */
	public static void main(String[] args) throws NoSuchElementException {
		COMMAND com;
		TextProcessor procTexto =load();
		Scanner s = new Scanner(System.in);
		while (s.hasNext()){
			try{
				com = COMMAND.valueOf(s.next());
				processCom(com, s, procTexto);
				System.out.println();
			}catch(NoSuchElementException n){
				
			}
		}
		store(procTexto);
		s.close();
	}

	private static void processCom(COMMAND com, Scanner s, TextProcessor procTexto) {
		switch(com){
			case AD: doAD(s, procTexto); break;
			case PC: doPC(s, procTexto); break;
			case AT: doAT(s, procTexto); break;
			case RT: doRT(s, procTexto); break;
			case LT: doLT(s, procTexto); break;
			case LR: doLR(s, procTexto); break;
			case LE: doLE(s, procTexto); break;
			case FP: doFP(s, procTexto); break;
			case LF: doLF(s, procTexto); break;
		}
		
	}

	private static void doAD(Scanner s, TextProcessor procTexto) {
		int numWord = s.nextInt();
		String word;
		int dictionaryCheck = 0;
		s.nextLine();
		for(int i=0; i<numWord; i++){
			word = s.next();
			if(!procTexto.wordExistsDictionary(word)){
				procTexto.addDictionary(word);
			}
			else{
				dictionaryCheck++;
			}
			s.nextLine();
		}
		if(dictionaryCheck<numWord)
			System.out.println(ACTDICIONARIO);
		else
			System.out.println(NAOACTDICIONARIO);
	}
	
	private static void doPC(Scanner s, TextProcessor procTexto) {
		String word = s.next();
		if(procTexto.wordExistsDictionary(word))
			System.out.println(EXISTEDICIONARIO);
		else
			System.out.println(NAOEXISTEDICIONARIO);
	}
	
	private static void doAT(Scanner s, TextProcessor procTexto) {
		String line, id = s.next();
		if(!procTexto.hasText(id)){
			int numLine = s.nextInt();
			String[] texto = new String[numLine]; 
			s.nextLine();
			for(int i=0; i<numLine; i++){
				line = s.nextLine();
				texto[i] = line;
			}
			procTexto.addText(id, numLine, texto);
			System.out.println(ADDTEXT);
		}
		else{
			int numLine = s.nextInt();
			s.nextLine();
			for(int i=0; i<numLine; i++){
				s.nextLine();
		}
			System.out.println(NAOADDTEXT);
		}
		
	}
	
	private static void doRT(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		s.nextLine();
		if(procTexto.removeText(id))
			System.out.println(REMOVERTEXTO);
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void doLT(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		s.nextLine();
		if(procTexto.hasText(id)){
			System.out.println(procTexto.listText(id, 1, 0));
		}
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void doLR(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		int min, max;
		min = s.nextInt();
		max = s.nextInt();
		s.nextLine();
		if(procTexto.hasText(id)){
			if(min>max && max !=0)
				System.out.println(LINHASTROCADAS);
			else if(procTexto.getText(id).getnLines()<max)
				System.out.println(LINHASMAXIMASERRADAS);
			else
				System.out.println(procTexto.listText(id, min, max));
		}
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void doLE(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		Iterator<Word> erros;
		s.nextLine();
		if(procTexto.hasText(id)){
			erros = procTexto.listWordByType(id, "E");
			if(erros.hasNext()){
				Word aux;
				while(erros.hasNext()){
					int auxint, previous = -1;
					aux = erros.next();
					System.out.println(aux.GetWord());
					Iterator<Integer> it = aux.GetLine();
					while(it.hasNext()){
						auxint = it.next();
						if(auxint != previous){
							System.out.println(auxint);
							previous = auxint;
						}						
					}
				}
			}
			else
				System.out.println(NAOERROR);
		}
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void doFP(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		String word = s.next();
		s.nextLine();
		if(procTexto.hasText(id)){
			System.out.printf(NUMOCORRENCIAS ,word ,procTexto.countTimes(id, word));
			System.out.println();
		}
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void doLF(Scanner s, TextProcessor procTexto) {
		String id = s.next();
		int failsafe = 0;
		String type = s.next();
		int freq = s.nextInt();
		Iterator<Word> words;
		s.nextLine();
		if(procTexto.hasText(id)){
			words = procTexto.listWordByType(id, type);
			Word aux;
			while(words.hasNext()){
				aux = words.next();
				if(aux.countTimes()==freq){
					failsafe++;
					System.out.println(aux.GetWord());
				}
			}
			if(failsafe<1)
				System.out.println(PALAVRASFREQUENCIA);
		}
		else
			System.out.println(NAOREMOVERTEXTO);
		
	}
	
	private static void store(TextProcessor procText){
		try{
			ObjectOutputStream file = new ObjectOutputStream(new FileOutputStream("save.txt"));
			file.writeObject(procText);
			file.flush();
			file.close();
		}catch (FileNotFoundException e){
		}
		catch ( IOException e){
		}
	}
	
	private static TextProcessor load(){
			TextProcessor procText = null;
			try{
			ObjectInputStream file = new ObjectInputStream(new FileInputStream("save.txt"));
			procText = (TextProcessor) file.readObject();
			file.close();
		}
		catch(IOException e){
			procText = new TextProcessorClass();

		}
		catch(ClassNotFoundException e){
			procText = new TextProcessorClass();
		}
			return procText;
	}
}
